package edu.hwadee.BEIS.serviceImpl;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.transaction.Transactional;

import edu.hwadee.BEIS.dto.*;
import edu.hwadee.BEIS.entity.*;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import edu.hwadee.BEIS.constants.CustomException;
import edu.hwadee.BEIS.constants.ResultEnum;
import edu.hwadee.BEIS.service.SystemManageService;
import edu.hwadee.BEIS.util.DataUtil;
import edu.hwadee.BEIS.util.FileUtil;

@Service
@Transactional
public class SystemManageServiceImpl extends BaseService implements SystemManageService {

    @Override
    public boolean validCertificate(String userType, String code) {

        Certificate certificate = certificateRepo.findOneByCode(code);
        if (certificate == null) {
            // 凭证不存在
            return false;
        } else {
            return certificate.getUserType().equals(userType);
        }
    }

    @Override
    public boolean register(SchoolUser schoolUser) {
        String salt = DataUtil.getRandom(6);
        String pwd = schoolUser.getSchoolUserPwd();
        pwd = DataUtil.SHA512(DataUtil.SHA512(pwd) + salt) + "$" + salt;
        schoolUser.setSchoolUserPwd(pwd);
        schoolUserRepo.save(schoolUser);
        return true;
    }

    @Override
    public boolean register(CountyUserDTO countyUserInfor) {
        CountyUser countyUser = new CountyUser();
        countyUser.setCountyUserId(countyUserInfor.getCountyUserId());
        countyUser.setCountyUserPwd(countyUserInfor.getCountyUserPwd());
        countyUser.setAdminCode(countyUserInfor.getAdminCode());
        countyUser.setCountyAddress(countyUserInfor.getCountyAddress());
        countyUser.setCountyEdbName(countyUserInfor.getCountyEdbName());
        countyUser.setCountyUserPhone(countyUserInfor.getCountyUserPhone());
        countyUser.setCertificate(certificateRepo.findOneByCode(countyUserInfor.getCertificate_code()));

        String salt = DataUtil.getRandom(6);
        String pwd = countyUser.getCountyUserPwd();
        pwd = DataUtil.SHA512(DataUtil.SHA512(pwd) + salt) + "$" + salt;
        countyUser.setCountyUserPwd(pwd);
        countyUserRepo.save(countyUser);
        return true;
    }

    @Override
    public boolean register(CityUserDTO cityUserInfor) {
        CityUser cityUser = new CityUser();
        cityUser.setCityUserId(cityUserInfor.getCityUserId());
        cityUser.setCityUserPwd(cityUserInfor.getCityUserPwd());
        cityUser.setAdminCode(cityUserInfor.getAdminCode());
        cityUser.setCityAddress(cityUserInfor.getCityAddress());
        cityUser.setCityEdbName(cityUserInfor.getCityEdbName());
        cityUser.setCityUserPhone(cityUserInfor.getCityUserPhone());
        cityUser.setCertificate(certificateRepo.findOneByCode(cityUserInfor.getCertificate_code()));

        String salt = DataUtil.getRandom(6);
        String pwd = cityUser.getCityUserPwd();
        pwd = DataUtil.SHA512(DataUtil.SHA512(pwd) + salt) + "$" + salt;
        cityUser.setCityUserPwd(pwd);
        cityUserRepo.save(cityUser);
        return true;
    }

    @Override
    public boolean register(LeaderUserDTO leaderUserInfor) {
        LeaderUser leaderUser = new LeaderUser();
        leaderUser.setLeaderUserId(leaderUserInfor.getLeaderUserId());
        leaderUser.setLeaderUserPwd(leaderUserInfor.getLeaderUserPwd());
        leaderUser.setLeaderUserName(leaderUserInfor.getLeaderUserName());
        leaderUser.setLeaderUserPhone(leaderUserInfor.getLeaderUserPhone());
        leaderUser.setCertificate(certificateRepo.findOneByCode(leaderUserInfor.getCertificate_code()));

        String salt = DataUtil.getRandom(6);
        String pwd = leaderUser.getLeaderUserPwd();
        pwd = DataUtil.SHA512(DataUtil.SHA512(pwd) + salt) + "$" + salt;
        leaderUser.setLeaderUserPwd(pwd);
        leaderUserRepo.save(leaderUser);
        return true;
    }

    @Override
    public boolean login(String userType, String user_id, String pwd) {
        switch (userType) {
            case "1":
                SchoolUser schoolUser;
                if (schoolUserRepo.exists(user_id)) {
                    schoolUser = schoolUserRepo.findOne(user_id);
                    String password = (schoolUser.getSchoolUserPwd().split("\\$"))[0];
                    String salt = (schoolUser.getSchoolUserPwd().split("\\$"))[1];
                    String shaString = DataUtil.SHA512(DataUtil.SHA512(pwd) + salt);
                    if (shaString.equals(password)) {
                        return true;
                    } else {
                        // 密码错误
                        throw new CustomException(ResultEnum.USER_PSW_WRONG);
                    }
                } else {
                    // 用户不存在
                    throw new CustomException(ResultEnum.USER_NOTEXIST);
                }

            case "2":
                CountyUser countyUser;
                if (countyUserRepo.exists(user_id)) {
                    countyUser = countyUserRepo.findOne(user_id);
                    String password = (countyUser.getCountyUserPwd().split("\\$"))[0];
                    String salt = (countyUser.getCountyUserPwd().split("\\$"))[1];
                    String shaString = DataUtil.SHA512(DataUtil.SHA512(pwd) + salt);
                    if (shaString.equals(password)) {
                        return true;
                    } else {
                        // 密码错误
                        throw new CustomException(ResultEnum.USER_PSW_WRONG);
                    }
                } else {
                    // 用户不存在
                    throw new CustomException(ResultEnum.USER_NOTEXIST);
                }
            case "3":
                CityUser cityUser;
                if (cityUserRepo.exists(user_id)) {
                    cityUser = cityUserRepo.findOne(user_id);
                    String password = (cityUser.getCityUserPwd().split("\\$"))[0];
                    String salt = (cityUser.getCityUserPwd().split("\\$"))[1];
                    String shaString = DataUtil.SHA512(DataUtil.SHA512(pwd) + salt);
                    if (shaString.equals(password)) {
                        return true;
                    } else {
                        // 密码错误
                        throw new CustomException(ResultEnum.USER_PSW_WRONG);
                    }
                } else {
                    // 用户不存在
                    throw new CustomException(ResultEnum.USER_NOTEXIST);
                }
            case "4":
                LeaderUser leaderUser;
                if (leaderUserRepo.exists(user_id)) {
                    leaderUser = leaderUserRepo.findOne(user_id);
                    String password = (leaderUser.getLeaderUserPwd().split("\\$"))[0];
                    String salt = (leaderUser.getLeaderUserPwd().split("\\$"))[1];
                    String shaString = DataUtil.SHA512(DataUtil.SHA512(pwd) + salt);
                    if (shaString.equals(password)) {
                        return true;
                    } else {
                        // 密码错误
                        throw new CustomException(ResultEnum.USER_PSW_WRONG);
                    }
                } else {
                    // 用户不存在
                    throw new CustomException(ResultEnum.USER_NOTEXIST);
                }
            default:
                return false;
        }
    }

    @Override
    public boolean schoolIsExisted(String school_id) {
        return schoolBasicInforRepo.exists(school_id);
    }

    @Override
    public SchoolUser schoolUserInfor2Object(SchoolUserDTO schoolUserDTO) throws Exception {
        if (schoolBasicInforRepo.exists(schoolUserDTO.getSchoolId())) {
            // 学校已存在
            throw new CustomException(ResultEnum.SCHOOL_ISEXITED);
        } else if (schoolUserRepo.exists(schoolUserDTO.getSchoolUserId())) {
            // 学校用户名已存在
            throw new CustomException(ResultEnum.SCHOOLUSER_ISEXISTED);
        } else {
            SchoolBasicInfor schoolBasicInfor = new SchoolBasicInfor(schoolUserDTO.getSchoolId());
            schoolBasicInfor.setSchoolName(schoolUserDTO.getSchoolName());
            schoolBasicInfor.setSchoolEnglishname(schoolUserDTO.getSchoolEnglishname());
            schoolBasicInfor.setSchoolAddress(schoolUserDTO.getSchoolAddress());
            schoolBasicInforRepo.save(schoolBasicInfor);
            SchoolUser schoolUser = new SchoolUser();
            schoolUser.setSchoolUserId(schoolUserDTO.getSchoolUserId());
            schoolUser.setCertificate(certificateRepo.findOneByCode(schoolUserDTO.getCertificate_code()));
            schoolUser.setSchoolBasic(schoolBasicInfor);
            schoolUser.setSchoolUserPwd(schoolUserDTO.getSchoolUserPwd());
            schoolUser.setSchoolUserPhone(schoolUserDTO.getSchoolUserPhone());
            return schoolUser;

        }

    }

    @Override
    public boolean schoolUsersAreExisted(Set<String> school_user_idSet) {
        boolean isExisted = true;
        for (String school_user_id : school_user_idSet) {
            if (!schoolUserRepo.exists(school_user_id)) {
                isExisted = false;
                break;
            }
        }
        return isExisted;
    }

    @Override
    public boolean OpenModifyIsExisted(Integer type_code) {
        return openModifyRepo.findOneByTypeCode(type_code) != null;
    }

    @Override
    public void saveOpenModify(OpenModify openModify) {
        openModifyRepo.save(openModify);
    }

    @Override
    public OpenModify OpenModifyInfor2Object(OpenModifyDTO openModifyInfor) throws Exception {
        if (schoolUsersAreExisted(openModifyInfor.getSchool_user_id_set())) {
            Set<SchoolUser> schoolUsers = schoolUserRepo.findBySchoolUserIdIn(openModifyInfor.getSchool_user_id_set());
            OpenModify openModify = openModifyRepo.findOneByTypeCode(openModifyInfor.getTypeCode());
            if (openModify == null) {
                openModify = new OpenModify();
            }
            openModify.setTypeCode(openModifyInfor.getTypeCode());
            openModify.setStartTime(openModifyInfor.getStartTime());
            openModify.setEndTime(openModifyInfor.getEndTime());
            openModify.setSchoolUsers(schoolUsers);
            return openModify;
        } else {
            // 指定用户不存在
            throw new CustomException(ResultEnum.SCHOOL_USER_NOTEXIST);
        }


    }

    @Override
    public List<OpenModify> getAllOpenModify() {
        return openModifyRepo.findAll();
    }

    @Override
    public Page<ProjectDeclare> getAllProjectDeclare(Pageable pageable) {
        return projectDeclareRepo.findByCountyAuditStatusIsAndCityAuditStatusIsOrderByModifyTimeDesc(pageable, (short) 1, (short) 1);
    }

    @Override
    public Page<ProjectDeclare> getCountryProjectDeclare(Pageable pageable) {
        return projectDeclareRepo.findByCountyAuditStatusIsAndCityAuditStatusIsAndProjectDeclareTypeIsOrderByModifyTime(pageable, (short) 1, (short) 1, "中央项目");
    }

    @Override
    public Page<ProjectDeclare> getProvinceProjectDeclare(Pageable pageable) {
        return projectDeclareRepo.findByCountyAuditStatusIsAndCityAuditStatusIsAndProjectDeclareTypeIsOrderByModifyTime(pageable, (short) 1, (short) 1, "省级项目");
    }

    @Override
    public Page<ProjectDeclare> getCityProjectDeclare(Pageable pageable) {
        return projectDeclareRepo.findByCountyAuditStatusIsAndCityAuditStatusIsAndProjectDeclareTypeIsOrderByModifyTime(pageable, (short) 1, (short) 1, "市级项目");
    }

    @Override
    public AnalysisDiagram analysisDiagramData2Object(AnalysisDiagramDTO analysisiDiagramInfor) throws Exception {
        if (!projectDeclareIsExisted(analysisiDiagramInfor.getProjectDeclareId())) {
            // 项目申报记录不存在
            throw new CustomException(ResultEnum.PROJECTDACLARE_NOTEXIST);
        } else if (analysisiDiagramInfor.getFile().isEmpty()) {
            // 上传图表为空
            throw new CustomException(ResultEnum.ANALYSISDIAGRAM_EMPTY);
        } else {
            AnalysisDiagram analysisDiagram = new AnalysisDiagram();
            analysisDiagram.setProjectDeclare(projectDeclareRepo.findOne(analysisiDiagramInfor.getProjectDeclareId()));
            MultipartFile file = analysisiDiagramInfor.getFile();

            String filePath = FileUtil.saveFile("analysisDiagram", file, analysisiDiagramInfor.getProjectDeclareId() + "_" + file.getOriginalFilename());
            analysisDiagram.setAnalysisDiagramFile(filePath);
            return analysisDiagram;
        }
    }

    @Override
    public boolean projectDeclareIsExisted(Integer project_id) {
        return projectDeclareRepo.exists(project_id);
    }

    @Override
    public void saveAnalysisDiagram(AnalysisDiagram analysisDiagram) {
        analysisDiagramRepo.save(analysisDiagram);
    }

    @Override
    public List<AnalysisDiagram> getAnalysisDiagramByProjectId(Integer projectDeclare_Id) throws Exception {
        if (projectDeclareRepo.exists(projectDeclare_Id)) {
            ProjectDeclare projectDeclare = projectDeclareRepo.findOne(projectDeclare_Id);
            return analysisDiagramRepo.findByProjectDeclare(projectDeclare);
        } else {
            throw new CustomException(ResultEnum.PROJECTDACLARE_NOTEXIST);
        }

    }

    @Override
    public void deleteAnalysisDiagram(Integer diagram_id) throws Exception {
        if (!analysisDiagramRepo.exists(diagram_id)) {
            throw new CustomException(ResultEnum.ANALYSISDIAGRAM_NOTEXIST);
        } else {
            AnalysisDiagram analysisDiagram = analysisDiagramRepo.findOne(diagram_id);
            String filePath = analysisDiagram.getAnalysisDiagramFile();
            if (FileUtil.deleteFile(filePath)) {
                analysisDiagramRepo.delete(diagram_id);
            } else {
                throw new CustomException(ResultEnum.ANALYSISDIAGRAM_DELETE_FAILURE);
            }
        }
    }

    @Override
    public List<Certificate> getAllCertificate() {
        return certificateRepo.findAll();
    }

    @Override
    public void saveCertificate(Certificate certificate) {
        certificateRepo.save(certificate);
    }

    @Override
    public void deleteCertificate(Integer certificateId) {
        certificateRepo.delete(certificateId);
    }

    @Override
    public Page<SchoolUser> getAllSchoolUser(Pageable pageable) {
        return schoolUserRepo.findAll(pageable);
    }

    @Override
    public Page<CountyUser> getAllCountyUser(Pageable pageable) {
        return countyUserRepo.findAll(pageable);
    }

    @Override
    public Page<CityUser> getAllCityUser(Pageable pageable) {
        return cityUserRepo.findAll(pageable);
    }

    @Override
    public Page<LeaderUser> getAllLeaderUser(Pageable pageable) {
        return leaderUserRepo.findAll(pageable);
    }

    @Override
    public void modifySchoolUser(SchoolUserDTO schoolUserDTO) {
        SchoolUser schoolUser = schoolUserRepo.findOne(schoolUserDTO.getSchoolUserId());
        String salt = DataUtil.getRandom(6);
        String pwd = schoolUserDTO.getSchoolUserPwd();
        pwd = DataUtil.SHA512(DataUtil.SHA512(pwd) + salt) + "$" + salt;
        schoolUser.setSchoolUserPwd(pwd);
        schoolUser.setCertificate(certificateRepo.findOneByCode(schoolUserDTO.getCertificate_code()));
        schoolUser.setSchoolUserPhone(schoolUserDTO.getSchoolUserPhone());
        schoolUserRepo.save(schoolUser);
    }

    @Override
    public void modifyCountyUser(CountyUserDTO countyUserDTO) {
        CountyUser countyUser = countyUserRepo.findOne(countyUserDTO.getCountyUserId());
        String salt = DataUtil.getRandom(6);
        String pwd = countyUserDTO.getCountyUserPwd();
        pwd = DataUtil.SHA512(DataUtil.SHA512(pwd) + salt) + "$" + salt;
        countyUser.setCountyUserPwd(pwd);
        countyUser.setAdminCode(countyUserDTO.getAdminCode());
        countyUser.setCertificate(certificateRepo.findOneByCode(countyUserDTO.getCertificate_code()));
        countyUser.setCountyAddress(countyUserDTO.getCountyAddress());
        countyUser.setCountyEdbName(countyUserDTO.getCountyEdbName());
        countyUser.setCountyUserPhone(countyUserDTO.getCountyUserPhone());
        countyUserRepo.save(countyUser);
    }

    @Override
    public void modifyCityUser(CityUserDTO cityUserDTO) {
        CityUser cityUser = cityUserRepo.findOne(cityUserDTO.getCityUserId());
        String salt = DataUtil.getRandom(6);
        String pwd = cityUserDTO.getCityUserPwd();
        pwd = DataUtil.SHA512(DataUtil.SHA512(pwd) + salt) + "$" + salt;
        cityUser.setCityUserPwd(pwd);
        cityUser.setAdminCode(cityUserDTO.getAdminCode());
        cityUser.setCertificate(certificateRepo.findOneByCode(cityUserDTO.getCertificate_code()));
        cityUser.setCityAddress(cityUserDTO.getCityAddress());
        cityUser.setCityEdbName(cityUserDTO.getCityEdbName());
        cityUser.setCityUserPhone(cityUserDTO.getCityUserPhone());
        cityUserRepo.save(cityUser);
    }

    @Override
    public void modifyLeaderUser(LeaderUserDTO leaderUserDTO) {
        LeaderUser leaderUser = leaderUserRepo.findOne(leaderUserDTO.getLeaderUserId());
        String salt = DataUtil.getRandom(6);
        String pwd = leaderUserDTO.getLeaderUserPwd();
        pwd = DataUtil.SHA512(DataUtil.SHA512(pwd) + salt) + "$" + salt;
        leaderUser.setLeaderUserPwd(pwd);
        leaderUser.setCertificate(certificateRepo.findOneByCode(leaderUserDTO.getCertificate_code()));
        leaderUser.setLeaderUserName(leaderUserDTO.getLeaderUserName());
        leaderUser.setLeaderUserPhone(leaderUserDTO.getLeaderUserPhone());
        leaderUserRepo.save(leaderUser);
    }

    @Override
    public boolean modifyPwd(String user_type, String user_id, String newPwd) {
        String salt = DataUtil.getRandom(6);
        switch (user_type) {
            case "1":
                SchoolUser schoolUser = schoolUserRepo.findOne(user_id);
                newPwd = DataUtil.SHA512(DataUtil.SHA512(newPwd) + salt) + "$" + salt;
                schoolUser.setSchoolUserPwd(newPwd);
                schoolUserRepo.save(schoolUser);
                return true;
            case "2":
                CountyUser countyUser = countyUserRepo.findOne(user_id);
                newPwd = DataUtil.SHA512(DataUtil.SHA512(newPwd) + salt) + "$" + salt;
                countyUser.setCountyUserPwd(newPwd);
                countyUserRepo.save(countyUser);
                return true;
            case "3":
                CityUser cityUser = cityUserRepo.findOne(user_id);
                newPwd = DataUtil.SHA512(DataUtil.SHA512(newPwd) + salt) + "$" + salt;
                cityUser.setCityUserPwd(newPwd);
                cityUserRepo.save(cityUser);
                return true;
            case "4":
                LeaderUser leaderUser = leaderUserRepo.findOne(user_id);
                newPwd = DataUtil.SHA512(DataUtil.SHA512(newPwd) + salt) + "$" + salt;
                leaderUser.setLeaderUserPwd(newPwd);
                leaderUserRepo.save(leaderUser);
                return true;
            default:
                return false;
        }
    }

    @Override
    public Page<Announcement> findSchoolUserAnnoucement(Pageable pageable, String schoolUserId) {
        if (schoolIsExisted(schoolUserId)) {
            Set<SchoolUser> schoolUsers = new HashSet<SchoolUser>();
            schoolUsers.add(schoolUserRepo.findOne(schoolUserId));
            return announcementRepo.findBySchoolUsers(pageable, schoolUsers);
        } else {
            // 学校用户不存在
            throw new CustomException(ResultEnum.SCHOOL_USER_NOTEXIST);
        }

    }

    @Override
    public Page<Announcement> findCountyUserAnnouncement(Pageable pageable, String countyUserId) {
        return null;
    }

    @Override
    public Page<Announcement> findLeaderUserAnnouncement(Pageable pageable, String leaderUserId) {
        return null;
    }

    @Override
    public Page<Announcement> findCityUserAnnouncement(Pageable pageable, String cityUserId) {
        return null;
    }

    @Override
    public void publishAnnouncement(AnnoucementDTO annoucementDTO, String cityUserId) {
        Announcement announcement = new Announcement();
        BeanUtils.copyProperties(annoucementDTO, announcement);
        announcement.setPublishTime(new Date());
        announcement.setSchoolUsers(schoolUserRepo.findBySchoolUserIdIn(annoucementDTO.getSchoolUserIds()));
        announcement.setCountyUsers(countyUserRepo.findByCountyUserIdIn(annoucementDTO.getCountyUserIds()));
        announcement.setLeaderUsers(leaderUserRepo.findByLeaderUserIdIn(annoucementDTO.getLeaderUserIds()));
        announcement.setCityUser(cityUserRepo.findOne(cityUserId));
        announcement = announcementRepo.save(announcement);
        announcement.setAnnouncementFile(FileUtil.saveFile("announcement", annoucementDTO.getAttachmentFile(), "" + announcement.getAnnouncementId() + "_" + annoucementDTO.getAttachmentFile().getOriginalFilename()));
        announcementRepo.save(announcement);
    }

    @Override
    public boolean adminCodeIsBeenUsed(String admin_code) {
        return countyUserRepo.findDistinctByAdminCode(admin_code) != null || cityUserRepo.findDistinctByAdminCode(admin_code) != null;
    }

    @Override
    public boolean countyUserIsExisted(String countyUser_id) {
        return countyUserRepo.exists(countyUser_id);
    }

    @Override
    public boolean cityUserIsExisted(String cityUser_id) {
        return cityUserRepo.exists(cityUser_id);
    }

    @Override
    public boolean leaderUserIsExisted(String leaderUser_id) {
        return leaderUserRepo.exists(leaderUser_id);
    }

}
